#include "auth_manager.h"
#include "config_api.h"
#include "manager_queue_comm.h"
#include "module_queue_struct.h"
#include "uc_wiota_api.h"
#include "userid_manager.h"
#include <rtdevice.h>
#include <rtthread.h>

#define DBG_ENABLE
#define DBG_SECTION_NAME "roll_call"
#include "uc_log.h"

#define ROLL_CALL_DEFAULT_TIME (10 * 60 * 1000)
#define MIN_ROLL_CALL_SUC_RATE 70

// 点名定时器
static rt_timer_t g_roll_call_timer = RT_NULL;
static unsigned char g_roll_call_flag = 0;
static unsigned int g_roll_call_total_num = 0;
static unsigned int g_roll_call_suc_num = 0;
static unsigned int g_roll_call_fail_num = 0;

/**
 * @brief 总的空消息数量加1
 *
 */
void manager_roll_call_total_num_inc(void)
{
    g_roll_call_total_num++;
}

/**
 * @brief 获取总的空消息数量
 *
 * @return unsigned int
 */
unsigned int manager_roll_call_total_num_get(void)
{
    return g_roll_call_total_num;
}

/**
 * @brief 总的空消息成功数量加1
 *
 */
void manager_roll_call_suc_num_inc(void)
{
    g_roll_call_suc_num++;
}

/**
 * @brief 总的空消息失败数量加1
 *
 */
void manager_roll_call_fail_num_inc(void)
{
    g_roll_call_fail_num++;
}

/**
 * @brief 清空空消息数量
 *
 */
static void manager_roll_call_num_clear(void)
{
    g_roll_call_total_num = 0;
    g_roll_call_suc_num = 0;
    g_roll_call_fail_num = 0;
}

/**
 * @brief 点名定时器超时回调函数
 *
 * @param parameter
 */
static void manager_handle_roll_call_timeout(void *parameter)
{
    // 模拟WIoTa APP发送点名消息给manger ul
    module_queue_communication(module_get_queue(GATEWAY_MANAGER_MODULE),
                               WIOTA_APP_MODULE,
                               GATEWAY_MANAGER_MODULE,
                               WIOTA_ROLL_CALL,
                               RT_NULL);
}

/**
 * @brief 创建点名定时器
 *
 */
void manager_roll_call_timer_create(void)
{
    unsigned int roll_call_time = uc_static_get_gateway_timed_cfg()->roll_call_time * 60 * 1000; // min -> ms

    if (g_roll_call_timer == RT_NULL)
    {
        g_roll_call_timer = rt_timer_create("rc_timer",
                                            manager_handle_roll_call_timeout,
                                            RT_NULL,
                                            roll_call_time > 0 ? roll_call_time : ROLL_CALL_DEFAULT_TIME,
                                            RT_TIMER_FLAG_PERIODIC | RT_TIMER_FLAG_SOFT_TIMER);
        RT_ASSERT(g_roll_call_timer);
    }
}

/**
 * @brief 启动点名定时器
 *
 */
void manager_roll_call_timer_start(void)
{
    unsigned int roll_call_time = uc_static_get_gateway_timed_cfg()->roll_call_time * 60 * 1000; // min -> ms

    if (g_roll_call_timer != RT_NULL)
    {
        if (roll_call_time > 0 && g_roll_call_flag == 0)
        {
            rt_timer_control(g_roll_call_timer, RT_TIMER_CTRL_SET_TIME, (void *)&roll_call_time);
            rt_timer_start(g_roll_call_timer);
            g_roll_call_flag = 1;
            TRACE_I("roll_call timer start, timeout %u", roll_call_time);
        }
    }
}

/**
 * @brief 停止点名定时器
 *
 */
void manager_roll_call_timer_stop(void)
{
    if (g_roll_call_timer != RT_NULL)
    {
        rt_timer_stop(g_roll_call_timer);
        g_roll_call_flag = 0;
        TRACE_D("roll_call timer stop");
    }
}

/**
 * @brief 删除点名定时器
 *
 */
void manager_roll_call_timer_del(void)
{
    if (g_roll_call_timer != RT_NULL)
    {
        rt_timer_stop(g_roll_call_timer);
        rt_timer_delete(g_roll_call_timer);
        g_roll_call_timer = RT_NULL;
        g_roll_call_flag = 0;
        manager_roll_call_num_clear();
        TRACE_D("roll_call timer del");
    }
}

/**
 * @brief 重置点名定时器
 *
 */
void manager_roll_call_timer_reset(void)
{
    unsigned char is_empty = manager_auth_list_is_empty();

    if (!is_empty)
    {
        manager_roll_call_timer_stop();
        manager_roll_call_timer_start();
    }
}

static void manager_calc_roll_call_suc_rate(struct rt_work *work, void *parameter)
{
    unsigned int total_num = g_roll_call_total_num;
    unsigned int suc_num = g_roll_call_suc_num;
    unsigned int fail_num = g_roll_call_fail_num;
    unsigned int suc_rate = 0;
    unsigned int roll_call_time = uc_static_get_gateway_timed_cfg()->roll_call_time * 60 * 1000; // min -> ms

    if (total_num > 0)
    {
        suc_rate = suc_num * 100 / total_num;
    }

    TRACE_I("total_num %d, suc_num %d, fail_num %d, suc_rate %d", total_num, suc_num, fail_num, suc_rate);

    if (suc_rate < MIN_ROLL_CALL_SUC_RATE)
    {
        // 点名失败较多，重启WIoTa
        module_queue_communication(module_get_queue(WIOTA_APP_MODULE),
                                   GATEWAY_MODULE_DEFAULT,
                                   WIOTA_APP_MODULE,
                                   WIOTA_APP_RESTART,
                                   RT_NULL);
    }
    else
    {
        // 发送成功，重置定时器
        manager_roll_call_timer_reset();
    }

    manager_roll_call_num_clear();

    rt_free(work);
}

/**
 * @brief 计算点名成功率的工作项
 *
 */
void manager_calc_roll_call_work(void)
{
    unsigned int calc_rate_delay = g_roll_call_total_num * uc_wiota_get_frame_len() / 1000 * 2 + 2000;
    struct rt_work *calc_rate_work = rt_malloc(sizeof(struct rt_work));
    RT_ASSERT(calc_rate_work);

    rt_work_init(calc_rate_work, manager_calc_roll_call_suc_rate, RT_NULL);
    rt_work_submit(calc_rate_work, calc_rate_delay);
    TRACE_I("submit calc_rate_work, delay %u", calc_rate_delay);
}